﻿using System.Windows;
using System.Windows.Controls;
using System.Collections.ObjectModel;

namespace MineLaunch.Controls
{
    [StyleTypedPropertyAttribute(Property = "ItemContainerStyle", StyleTargetType = typeof(DragDropListBoxItem))]
    public class DragDropListBox : ListBox
    {
        static DragDropListBox()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(DragDropListBox),
                new FrameworkPropertyMetadata(typeof(ListBox)));
        }

        #region ItemContainerStyle

        protected override void ClearContainerForItemOverride(DependencyObject element, object item)
        {
        }

        protected override bool IsItemItsOwnContainerOverride(object item)
        {
            return item is DragDropListBoxItem;
        }

        protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
        {
            var content = element as DragDropListBoxItem;
            if (element != item)
            {
                if (content != null)
                {
                    content.Content = item;
                    content.DataContext = item;
                }
            }
        }

        protected override DependencyObject GetContainerForItemOverride()
        {
            var listboxItem = new DragDropListBoxItem();
            listboxItem.parentListBox = this;
            return listboxItem;
        }

        #endregion

        protected override void OnDrop(DragEventArgs e)
        {
            var items = this.DataContext as ObservableCollection<DragDropItem>;
            var dropPosition = e.GetPosition(this);
            var lbi = e.Data.GetData(typeof(DragDropListBoxItem)) as DragDropListBoxItem;

            if (lbi == null || lbi.parentListBox != this) return;
            var o = lbi.DataContext as DragDropItem;
            var index = items.IndexOf(o);
            for (int i = 0; i < items.Count; i++)
            {
                var item = this.ItemContainerGenerator.ContainerFromIndex(i) as DragDropListBoxItem;
                var pos = this.PointFromScreen(item.PointToScreen(new Point(0, item.ActualHeight / 2)));
                if (dropPosition.Y < pos.Y)
                {
                    items.Move(index, (index < i) ? i - 1 : i);
                    return;
                }
            }
            int last = items.Count - 1;
            items.Move(index, last);
        }
    }
}
